// lib/src/utils/lunar_util.dart

class LunarUtil {
  // 农历数据（1900-2100），数据压缩
  // 每16位(2字节)数据代表一年，格式如下：
  // 15-12位：闰月月份（0表示无闰月）
  // 11-0位：12个月的大小（1为大月30天，0为小月29天）
  static const List<int> _lunarData = [
    0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0,
    0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,
    0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
    0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0,
    0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
    0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2,
    0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573,
    0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4,
    0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5,
    0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
    0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46,
    0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58,
    0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50,
    0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0,
    0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
    0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260,
    0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
    0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0,
    0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63, 0x09370,
    0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a654, 0x0ab60,
    0x09570, 0x04975, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0,
    0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552,
    0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4,
    0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,
    0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
    0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6,
    0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577,
    0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63, 0x09370, 0x049f8,
  ];

  static const List<String> _dayNames = [
    '初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十',
    '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十',
    '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十'
  ];

  static const List<String> _monthNames = [
    '正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '冬月', '腊月'
  ];

  // 节气
  static const List<String> _solarTerm = [
    "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨",
    "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑",
    "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
  ];
  static const List<int> _sTermInfo = [
    0, 21208, 42467, 63836, 85337, 107014, 128867, 150921,
    173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033,
    353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758
  ];

  // 获取某年的总天数
  static int _getYearDays(int year) {
    int sum = 348;
    for (int i = 0x8000; i > 0x8; i >>= 1) {
      if ((_lunarData[year - 1900] & i) != 0) sum += 1;
    }
    return sum + _getLeapMonthDays(year);
  }

  // 获取闰月天数
  static int _getLeapMonthDays(int year) {
    if (_getLeapMonth(year) != 0) {
      return (_lunarData[year - 1900] & 0x10000) != 0 ? 30 : 29;
    }
    return 0;
  }

  // 获取闰月
  static int _getLeapMonth(int year) {
    return _lunarData[year - 1900] & 0xf;
  }

  // 获取某月天数
  static int _getMonthDays(int year, int month) {
    if ((_lunarData[year - 1900] & (0x10000 >> month)) != 0) {
      return 30;
    }
    return 29;
  }

  // 获取节气
  static String _getSolarTerm(DateTime date) {
    DateTime baseDate = DateTime(1900, 1, 6, 2, 5);
    double y = date.year.toDouble();
    for (int i = _solarTerm.length - 1; i >= 0; i--) {
      double termTime = 365.2422 * (y - 1900) + _sTermInfo[i] / 60.0;
      DateTime termDate = baseDate.add(Duration(minutes: termTime.toInt()));
      if (date.year == termDate.year && date.month == termDate.month && date.day == termDate.day) {
        return _solarTerm[i];
      }
    }
    return "";
  }

  // 公历转农历
  static String getLunarDayString(DateTime date) {
    if (date.year < 1901 || date.year > 2099) {
      return "";
    }

    // 优先返回节气
    String solarTerm = _getSolarTerm(date);
    if (solarTerm.isNotEmpty) return solarTerm;

    // 传统节日
    if (date.month == 1 && date.day == 1) return '元旦';
    if (date.month == 2 && date.day == 14) return '情人节';
    if (date.month == 3 && date.day == 8) return '妇女节';
    if (date.month == 3 && date.day == 12) return '植树节';
    if (date.month == 4 && date.day == 1) return '愚人节';
    if (date.month == 5 && date.day == 1) return '劳动节';
    if (date.month == 5 && date.day == 4) return '青年节';
    if (date.month == 6 && date.day == 1) return '儿童节';
    if (date.month == 7 && date.day == 1) return '建党节';
    if (date.month == 8 && date.day == 1) return '建军节';
    if (date.month == 9 && date.day == 10) return '教师节';
    if (date.month == 10 && date.day == 1) return '国庆节';
    if (date.month == 12 && date.day == 25) return '圣诞节';


    int i, leap = 0, temp = 0;
    final baseDate = DateTime(1900, 1, 31);
    int offset = date.difference(baseDate).inDays;

    for (i = 1900; i < 2100 && offset > 0; i++) {
      temp = _getYearDays(i);
      offset -= temp;
    }

    if (offset < 0) {
      offset += temp;
      i--;
    }

    int year = i;
    leap = _getLeapMonth(year);
    bool isLeap = false;

    for (i = 1; i < 13 && offset > 0; i++) {
      if (leap > 0 && i == (leap + 1) && !isLeap) {
        --i;
        isLeap = true;
        temp = _getLeapMonthDays(year);
      } else {
        temp = _getMonthDays(year, i);
      }

      if (isLeap && i == (leap + 1)) isLeap = false;
      offset -= temp;
    }

    if (offset == 0 && leap > 0 && i == leap + 1) {
      if (isLeap) {
        isLeap = false;
      } else {
        isLeap = true;
        --i;
      }
    }
    if (offset < 0) {
      offset += temp;
      --i;
    }

    int month = i;
    int day = offset + 1;

    // 农历节日
    if (month == 1 && day == 1) return '春节';
    if (month == 1 && day == 15) return '元宵节';
    if (month == 5 && day == 5) return '端午节';
    if (month == 7 && day == 7) return '七夕节';
    if (month == 8 && day == 15) return '中秋节';
    if (month == 9 && day == 9) return '重阳节';
    if (month == 12 && day == 8) return '腊八节';
    if (month == 12 && (_getMonthDays(year, 12) == 29 ? day == 29 : day == 30)) return '除夕';


    final monthStr = (isLeap ? "闰" : "") + _monthNames[month - 1];
    final dayStr = _dayNames[day - 1];

    if (day == 1) return monthStr;
    return dayStr;
  }
}
